/*
     raw os - Copyright (C)  Lingjun Chen(jorya_txj).

    This file is part of raw os.

    raw os is free software; you can redistribute it it under the terms of the 
    GNU General Public License as published by the Free Software Foundation; 
    either version 3 of the License, or  (at your option) any later version.

    raw os is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 
    without even the implied warranty of  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
    See the GNU General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with this program. if not, write email to jorya.txj@gmail.com
                                      ---

    A special exception to the LGPL can be applied should you wish to distribute
    a combined work that includes raw os, without being obliged to provide
    the source code for any proprietary components. See the file exception.txt
    for full details of how and when the exception can be applied.
*/


/* 	2012-8  Created by jorya_txj
  *	xxxxxx   please added here
  */

#include <raw_api.h>
#include "qp_port.h"


#define  TEST_TASK_STK_SIZE 2048


PORT_STACK test_task_stack_qp[TEST_TASK_STK_SIZE];

PORT_STACK test_qp1_stack[TEST_TASK_STK_SIZE];

RAW_TASK_OBJ 		test_task_obj_qp;



void start_vc_timer(int tick_ms);


extern void  Uart_Printf(char*   f,   ...);




/*..........................................................................*/
enum SensorSignals {
    TIMEOUT_SIG = Q_USER_SIG,                /* the periodic timeout signal */
    DATA_READY_SIG,                         /* the invented reminder signal */
    TERMINATE_SIG                              /* terminate the application */
};
/*..........................................................................*/
typedef struct SensorTag {                      /* the Sensor active object */
    QActive super;                                   /* derive from QActive */

    QTimeEvt timeEvt;                       /* private time event generator */
    uint16_t pollCtr;
    uint16_t procCtr;
} Sensor;


void Sensor_ctor(Sensor *me);
                                          /* hierarchical state machine ... */
static QState Sensor_initial   (Sensor *me, QEvt const *e);
static QState Sensor_polling   (Sensor *me, QEvt const *e);
static QState Sensor_processing(Sensor *me, QEvt const *e);
static QState Sensor_idle      (Sensor *me, QEvt const *e);
static QState Sensor_busy      (Sensor *me, QEvt const *e);
static QState Sensor_final     (Sensor *me, QEvt const *e);

/*..........................................................................*/
void Sensor_ctor(Sensor *me) {
    QActive_ctor(&me->super, (QStateHandler)&Sensor_initial);
    QTimeEvt_ctor(&me->timeEvt, TIMEOUT_SIG);
}

/* HSM definition ----------------------------------------------------------*/
QState Sensor_initial(Sensor *me, QEvt const *e) {
    (void)e;               /* avoid compiler warning about unused parameter */

    me->pollCtr = 0;
    me->procCtr = 0;

    return Q_TRAN(&Sensor_polling);
}
/*..........................................................................*/
QState Sensor_final(Sensor *me, QEvt const *e) {
    (void)me;              /* avoid compiler warning about unused parameter */
    (void)e;               /* avoid compiler warning about unused parameter */
    switch (e->sig) {
        case Q_ENTRY_SIG: {
            Uart_Printf("final-ENTRY;\nBye!Bye!\n");
            QF_stop();                         /* terminate the application */
            return Q_HANDLED();
        }
    }
    return Q_SUPER(&QHsm_top);
}
/*..........................................................................*/
QState Sensor_polling(Sensor *me, QEvt const *e) {
    switch (e->sig) {
        case Q_ENTRY_SIG: {
                                       /* periodic timeout every 1/2 second */
            QTimeEvt_postEvery(&me->timeEvt, (QActive *)me,
                               RAW_TICKS_PER_SECOND / 2);
            return Q_HANDLED();
        }
        case Q_EXIT_SIG: {
            QTimeEvt_disarm(&me->timeEvt);
            return Q_HANDLED();
        }
        case Q_INIT_SIG: {
            return Q_TRAN(&Sensor_processing);
        }
        case TIMEOUT_SIG: {
            /* NOTE: this constant event is statically pre-allocated.
            * It can be posted/published as any other event.
            */
            static const QEvt reminderEvt = { DATA_READY_SIG, 0, 0 };

            ++me->pollCtr;
            Uart_Printf("polling %3d\n", me->pollCtr);
            if ((me->pollCtr & 0x3) == 0) {                     /* modulo 4 */
                QActive_postFIFO((QActive *)me, &reminderEvt);
            }
            return Q_HANDLED();
        }
        case TERMINATE_SIG: {
            return Q_TRAN(&Sensor_final);
        }
    }
    return Q_SUPER(&QHsm_top);
}
/*..........................................................................*/
QState Sensor_processing(Sensor *me, QEvt const *e) {
    switch (e->sig) {
        case Q_INIT_SIG: {
            return Q_TRAN(&Sensor_idle);
        }
    }
    return Q_SUPER(&Sensor_polling);
}
/*..........................................................................*/
QState Sensor_idle(Sensor *me, QEvt const *e) {
    switch (e->sig) {
        case Q_ENTRY_SIG: {
            Uart_Printf("idle-ENTRY;\n");
            return Q_HANDLED();
        }
        case DATA_READY_SIG: {
			 Uart_Printf("DATA_READY_SIG\n");
            return Q_TRAN(&Sensor_busy);
        }
    }
    return Q_SUPER(&Sensor_processing);
}
/*..........................................................................*/
QState Sensor_busy(Sensor *me, QEvt const *e) {
    switch (e->sig) {
        case Q_ENTRY_SIG: {
            Uart_Printf("busy-ENTRY;\n");
            return Q_HANDLED();
        }
        case TIMEOUT_SIG: {
            ++me->procCtr;
            Uart_Printf("processing %3d\n", me->procCtr);
            if ((me->procCtr & 0x1) == 0) {                     /* modulo 2 */
                return Q_TRAN(&Sensor_idle);
            }
            return Q_HANDLED();
        }
    }
    return Q_SUPER(&Sensor_processing);
}

/* test harness ============================================================*/

/* Local-scope objects -----------------------------------------------------*/
static Sensor l_sensor;                         /* the Sensor active object */
static QEvt const *l_sensorQSto[10];    /* Event queue storage for Sensor */

unsigned int test_qp1_count;
void Timer0Init(void);

void test_qp1(void * pParam) 
{	
	Timer0Init();
	
	QF_init();    /* initialize the framework and the underlying RT kernel */

	 /* publish-subscribe not used, no call to QF_psInit() */
    /* dynamic event allocation not used, no call to QF_poolInit() */

                             /* instantiate and start the active objects... */
    Sensor_ctor(&l_sensor);

    QActive_start((QActive *)&l_sensor, 1, l_sensorQSto, Q_DIM(l_sensorQSto),
                  (void *)test_qp1_stack, TEST_TASK_STK_SIZE, (QEvt *)0);
	
	while(1) {
		
		test_qp1_count++;
		raw_sleep(RAW_TICKS_PER_SECOND);	
		
	}
	
}



extern RAW_U8 test_started;

void qp_test()
{

	if (test_started) {

		return;

	}

	test_started = 1;
	
	
	raw_task_create(&test_task_obj_qp, (RAW_U8  *)"task1", 0,
	                         3, 0,  test_task_stack_qp, 
	                         TEST_TASK_STK_SIZE , test_qp1, 1); 



}



